package mi.payment.utils.secure;

import android.content.Context;
import android.os.RemoteException;
import android.text.TextUtils;

import com.sunmi.pay.hardware.aidl.AidlConstants;
import com.sunmi.pay.hardware.aidl.security.SecurityOpt;
import com.sunmi.pay.hardware.aidlv2.AidlConstantsV2;
import com.sunmi.pay.hardware.aidlv2.security.SecurityOptV2;

import java.util.Arrays;

import lainey.ui.utils.LogUtil;
import mi.payment.Constant;
import mi.payment.MyApplication;
import mi.payment.bean.settings.SecurityKeyAreaDistribution;
import mi.payment.settings.TerminalKeyDataOperations;
import mi.payment.settings.TerminalKeyManagementBean;
import mi.payment.utils.ByteUtil;
import mi.payment.utils.iso8583.FieldConfig;
import mi.payment.utils.iso8583.Utils;

import static com.sunmi.pay.hardware.aidl.AidlConstants.Security.KEY_ALG_TYPE_3DES;
import static mi.payment.settings.TerminalKeyManagementBean.THREE_DES;

/**
 * 密钥安全
 */
public class TerminalSecure {


    // 无处理要求
    public static final int PROCESSREQUEST_NONE = 0;
    // 下传终端磁条卡参数
    public static final int PROCESS_REQUEST_DOWN_MAG = 1;
    // 上传终端磁条卡状态信息
    public static final int PROCESS_REQUEST_UPLOAD_MAG = 2;
    // 重新签到
    public static final int PROCESS_REQUEST_RE_LOGON = 3;
    // 通知终端发起更新公钥信息操作
    public static final int PROCESS_REQUEST_NOTICE_UPDATE = 4;
    // 下载终端IC卡参数
    public static final int PROCESS_REQUEST_DOWN_IC = 5;
    // TMS参数下载
    public static final int PROCESS_REQUEST_DOWN_TMS = 6;
    // 卡BIN黑名单下载
    public static final int PROCESS_REQUEST_DOWN_BLACK = 7;
    // 币种汇率下载
    public static final int PROCESS_REQUEST_DOWN_RATE = 8;
    // 重新发起初始化
    public static final int PROCESS_REQUEST_RE_INIT = 9;

    public static byte[] MasterKey = {(byte) 0x2F, (byte) 0xD9, (byte) 0xD3, (byte) 0x26, (byte) 0x40, (byte) 0xF8, (byte) 0x83, (byte) 0xDF, (byte) 0x5D, (byte) 0x52, (byte) 0x01, (byte) 0x31, (byte) 0x8A, (byte) 0x37, (byte) 0xFE, (byte) 0x07};
    private static byte[] KeyEncryptKey = {(byte) 0x33, (byte) 0x33, (byte) 0x33, (byte) 0x33, (byte) 0x33, (byte) 0x33, (byte) 0x33,
            (byte) 0x33, (byte) 0x33, (byte) 0x33, (byte) 0x33, (byte) 0x33, (byte) 0x33, (byte) 0x33, (byte) 0x33, (byte) 0x33};

    private static byte[] PIK = new byte[16];
    private static byte[] MAK = new byte[16];
    private static byte[] TDK = new byte[16];
    public static int PIKIndex;
    public static int MAKIndex;
    public static int TDKIndex;
    public static int TMKIndex;
    public static int KEKIndex;
    public static String encryptionAlgorithm;

    /**
     * 保存终端主密钥到安全芯片,方法中包含使用KEK解密TMK并且打印出明文
     *
     * @param masterKeyEncrypted 终端主密钥
     * @return 0表示成功，其他表示失败
     */
    public static synchronized int SaveTMK(byte[] masterKeyEncrypted) {
        LogUtil.e(Constant.TAG, "saveTMK："
                + "\n 保存到索引：" + TMKIndex
                + "\n 密钥类型：1 \n 解密密钥索引：" + KEKIndex
                + "\n 加密类型：3 \n TMK密文：" + Arrays.toString(masterKeyEncrypted)
                + "\n length：" + masterKeyEncrypted.length);
        SecurityOpt securityOpt = MyApplication.getInstance().securityOpt;
        int result = -1;
        try {
            result = securityOpt.saveKey(AidlConstants.Security.KEY_TYPE_TMK, masterKeyEncrypted, null, KEKIndex, KEY_ALG_TYPE_3DES, TMKIndex, true);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (result == 0) {
            TerminalKeyDataOperations terminalKeyDataOperations = TerminalKeyDataOperations.getInstance();
            terminalKeyDataOperations.saveHasDownloadTMK(true);
        }
        return result;
    }

    /**
     * 保存终端主密钥到安全芯片,方法中包含使用KEK解密TMK并且打印出明文
     *
     * @param masterKeyEncrypted 终端主密钥
     * @return 0表示成功，其他表示失败
     */
    public static synchronized int SaveTMK(byte[] masterKeyEncrypted, byte[] cv) {
        LogUtil.e(Constant.TAG, "saveTMK："
                + "\n 保存到索引：" + TMKIndex
                + "\n 密钥类型：1 \n 解密密钥索引：" + KEKIndex
                + "\n 加密类型：3 \n TMK密文：" + Arrays.toString(masterKeyEncrypted)
                + "\n length：" + masterKeyEncrypted.length);
        SecurityOpt securityOpt = MyApplication.getInstance().securityOpt;
        int result = -1;
        try {
            result = securityOpt.saveKey(AidlConstants.Security.KEY_TYPE_TMK, masterKeyEncrypted, cv, KEKIndex, KEY_ALG_TYPE_3DES, TMKIndex, true);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (result == 0) {
            TerminalKeyDataOperations terminalKeyDataOperations = TerminalKeyDataOperations.getInstance();
            terminalKeyDataOperations.saveHasDownloadTMK(true);
        }
        return result;
    }

    public static synchronized int SaveTMK(byte[] masterKeyEncrypted, int saveIndex, int decodeIndex) {
        LogUtil.e(Constant.TAG, "saveTMK："
                + "\n 保存到索引：" + TMKIndex
                + "\n 密钥类型：1 \n 解密密钥索引：" + KEKIndex
                + "\n 加密类型：3 \n TMK密文：" + Arrays.toString(masterKeyEncrypted)
                + "\n length：" + masterKeyEncrypted.length);
        SecurityOpt securityOpt = MyApplication.getInstance().securityOpt;
        int result = -1;
        try {
            result = securityOpt.saveKey(AidlConstants.Security.KEY_TYPE_TMK, masterKeyEncrypted, null, decodeIndex, KEY_ALG_TYPE_3DES, saveIndex, true);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (result == 0) {
            TerminalKeyDataOperations terminalKeyDataOperations = TerminalKeyDataOperations.getInstance();
            terminalKeyDataOperations.saveHasDownloadTMK(true);
        }
        return result;
    }

    /**
     * Debug：调试时调用
     * 保存工作密钥，使用本地的算法验证checkValue
     */
    public static int SaveKeys(Context context, byte[] KeyBuff) {
        LogUtil.e(Constant.TAG, "KeyBuff:" + Utils.byte2HexStr(KeyBuff));
        byte[] temp = new byte[16]; // 工作密钥密文
        byte[] temp1 = new byte[8]; // 8个的0x00 用于算check value
        byte[] temp2;
        byte[] pospCheckValue = new byte[4];      // pospAccess checkValue
        byte[] calculateCheckValue = new byte[4]; // local checkValue

        byte[] plaintext = new byte[8];
        Arrays.fill(plaintext, (byte) 0x00);
        // initKey(context);
        try {
            // pik
            System.arraycopy(KeyBuff, 0, temp, 0, 16);
            System.arraycopy(TriDes.Des3DecodeECB2(MasterKey, temp), 0, PIK, 0, 16);
            LogUtil.e(Constant.TAG, "明文 --> MasterKey：" + Utils.byte2HexStr(MasterKey));
            LogUtil.e(Constant.TAG, "PIK密文：" + Utils.byte2HexStr(temp));
            LogUtil.e(Constant.TAG, "明文 --> PIK：" + Utils.byte2HexStr(PIK));
            Arrays.fill(temp1, (byte) 0x00);
            temp2 = TriDes.Des3EncodeECB2(PIK, temp1);
            System.arraycopy(temp2, 0, calculateCheckValue, 0, 4);
            LogUtil.e(Constant.TAG, "posp CheckValue Check PIK：" + Utils.byte2HexStr(calculateCheckValue));

            System.arraycopy(KeyBuff, 16, pospCheckValue, 0, 4);
            if (!Arrays.equals(pospCheckValue, calculateCheckValue)) {
                LogUtil.e(Constant.TAG, "posp CheckValue PIK Verify failed." + Utils.byte2HexStr(pospCheckValue));
                return -1;
            } else {
                // check value 校验成功 保存PIK到安全芯片
                LogUtil.e(Constant.TAG, "savePIK：" + " 保存到索引：" + PIKIndex + " 密钥类型：" + 2 +
                        " 解密密钥索引：" + TMKIndex + " 加密类型：" + 3 + " key_data：" + Arrays.toString(temp) +
                        " length：" + temp.length);
                int ret_savePIK = saveKey(PIKIndex, 2, TMKIndex, 3, temp, temp.length);
                if (ret_savePIK != 0) {
                    LogUtil.e(Constant.TAG, "ret_savePIK：" + ret_savePIK + " PIK保存失败!");
                    return -1;
                } else {
                    // save key success
                    byte[] outArr = new byte[8];
                    int result = dataEncrypt(PIKIndex, 2, 3, plaintext, outArr);
                    LogUtil.e(Constant.TAG, "dataEncrypt result：" + result);
                    LogUtil.e(Constant.TAG, "PIK 硬加密8个0：" + Utils.byte2HexStr(outArr));
                    outArr = TriDes.Des3EncodeECB2(PIK, plaintext);
                    LogUtil.e(Constant.TAG, "PIK 软加密8个0：" + Utils.byte2HexStr(outArr));
                }
            }

            // mak
            System.arraycopy(KeyBuff, 20, temp, 0, 16);
            System.arraycopy(TriDes.Des3DecodeECB2(MasterKey, temp), 0, MAK, 0, 16);
            LogUtil.e(Constant.TAG, "明文 --> MasterKey：" + Utils.byte2HexStr(MasterKey));
            LogUtil.e(Constant.TAG, "MAK密文：" + Utils.byte2HexStr(temp));
            LogUtil.e(Constant.TAG, "明文 --> MAK：" + Utils.byte2HexStr(MAK));

            Arrays.fill(temp1, (byte) 0x00);
            temp2 = TriDes.DesEncodeECB(MAK, temp1);

            System.arraycopy(temp2, 0, calculateCheckValue, 0, 4);
            LogUtil.e(Constant.TAG, "calculate CheckValue Check MAK：" + Utils.byte2HexStr(calculateCheckValue));
            System.arraycopy(KeyBuff, 36, pospCheckValue, 0, 4);
            if (!Arrays.equals(pospCheckValue, calculateCheckValue)) {
                LogUtil.e(Constant.TAG, "posp CheckValue MAK Verify failed." + Utils.byte2HexStr(pospCheckValue));
                return -2;
            } else {
                LogUtil.e(Constant.TAG, "saveMAK：" + " 保存到索引：" + MAKIndex + " 密钥类型:" + 5 +
                        " 解密密钥索引：" + TMKIndex + " 加密类型：" + 3 + " key_data：" + Arrays.toString(temp) +
                        " length：" + temp.length);
                int ret_saveMAK = saveKey(MAKIndex, 5, TMKIndex, 3, temp, temp.length);
                if (ret_saveMAK != 0) {
                    LogUtil.e(Constant.TAG, "ret_saveMAK：" + ret_saveMAK + " MAK保存失败!");
                    return -2;
                } else {
                    // save key success
                    byte[] outArr = new byte[8];
                    int result = dataEncrypt(MAKIndex, 5, 3, plaintext, outArr);
                    LogUtil.e(Constant.TAG, "dataEncrypt result：" + result);
                    LogUtil.e(Constant.TAG, "MAK 硬加密8个0：" + Utils.byte2HexStr(outArr));
                    outArr = TriDes.Des3EncodeECB2(MAK, plaintext);
                    LogUtil.e(Constant.TAG, "MAK 软加密8个0：" + Utils.byte2HexStr(outArr));
                }
            }

            // tdk
            System.arraycopy(KeyBuff, 40, temp, 0, 16);
            System.arraycopy(TriDes.Des3DecodeECB2(MasterKey, temp), 0, TDK, 0, 16);
            LogUtil.e(Constant.TAG, "明文 --> MasterKey：" + Utils.byte2HexStr(MasterKey));
            LogUtil.e(Constant.TAG, "TDK密文：" + Utils.byte2HexStr(temp));
            LogUtil.e(Constant.TAG, "明文 --> TDK：" + Utils.byte2HexStr(TDK));

            Arrays.fill(temp1, (byte) 0x00);
            temp2 = TriDes.Des3EncodeECB2(TDK, temp1);

            System.arraycopy(temp2, 0, calculateCheckValue, 0, 4);
            LogUtil.e(Constant.TAG, "calculate CheckValue Check TDK：" + Utils.byte2HexStr(calculateCheckValue));
            System.arraycopy(KeyBuff, 56, pospCheckValue, 0, 4);
            if (!Arrays.equals(calculateCheckValue, pospCheckValue)) {
                LogUtil.e(Constant.TAG, "posp CheckValue TDK Verify failed." + Utils.byte2HexStr(calculateCheckValue));
                return -3;
            } else {
                LogUtil.e(Constant.TAG, "saveTDK：" + " 保存到索引：" + TDKIndex + " 密钥类型：" + 5 +
                        " 解密密钥索引：" + TMKIndex + " 加密类型：" + 3 + " key_data：" + Arrays.toString(temp) +
                        " length：" + temp.length);
                int ret_saveTDK = saveKey(TDKIndex, 5, TMKIndex, 3, temp, temp.length);
                if (ret_saveTDK != 0) {
                    LogUtil.e(Constant.TAG, "ret_saveTDK：" + ret_saveTDK + " MAK保存失败!");
                    return -3;
                } else {
                    // save key success
                    byte[] outArr = new byte[8];
                    int result = dataEncrypt(TDKIndex, 5, 3, plaintext, outArr);
                    LogUtil.e(Constant.TAG, "dataEncrypt result：" + result);
                    LogUtil.e(Constant.TAG, "TDK 硬加密8个0：" + Utils.byte2HexStr(outArr));
                    outArr = TriDes.Des3EncodeECB2(TDK, plaintext);
                    LogUtil.e(Constant.TAG, "TDK 软加密8个0：" + Utils.byte2HexStr(outArr));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return -4;
        }

        return 0;
    }

    /**
     * 保存工作密钥 PIK,MAK,TDK,并且CheckValue
     *
     * @param workingKeyBytes 工作密钥的字节数组
     * @param is3des          是否是3des加密,否者单des (TMK 的加密方式和工作密钥是一样的)
     * @param trackEncode     是否需要磁道加密
     * @return 0：成功, -1：PIK保存失败, -2：MAK保存失败, -3：TDK保存失败
     * -4 PIK CheckValue 失败，-5 MAK CheckValue 失败，-6 TDK CheckValue 失败 -7 工作密钥长度错误
     */
    public static int SaveWorkingKeys(byte[] workingKeyBytes, boolean is3des, boolean trackEncode) {
        LogUtil.e(Constant.TAG, "workingKeyBytes：" + Utils.byte2HexStr(workingKeyBytes));
        SecurityOpt securityOpt = MyApplication.getInstance().securityOpt;
        int base = 20;
        if (is3des) {
            base = 20;
        } else {
            base = 12;
        }
        if (trackEncode) {
            base *= 3;
        } else {
            base *= 2;
        }
        if (workingKeyBytes.length != base) {
            return -7;
        }
        /*
         * ############ start ##############先存储工作密钥到安全芯片###################
         */
        byte[] key;
        byte[] checkValue;
        int keyLength;
        int index = 0;   // 密钥位置
        int encryptType; // 3des加密 3;des加密 2
        if (is3des) {
            encryptType = 3; // 3des加密
            keyLength = 16;
        } else {
            encryptType = 2; // des加密
            keyLength = 8;
        }
        checkValue = new byte[4];
        key = new byte[keyLength];

        // Save PIK
        System.arraycopy(workingKeyBytes, index * (keyLength + 4), key, 0, keyLength);
        System.arraycopy(workingKeyBytes, index * (keyLength + 4) + keyLength, checkValue, 0, 4);
        LogUtil.e(Constant.TAG, "PIK CheckValue：" + Utils.byte2HexStr(checkValue));
        index++;
        LogUtil.e(Constant.TAG, "savePIK："
                + "\n 保存到索引：" + PIKIndex
                + "\n 密钥类型：2 \n 解密密钥索引：" + TMKIndex
                + "\n 加密类型：3 \n pik密文：" + Arrays.toString(key)
                + "\n length：" + key.length);
        int pikRes = -1;
        try {
            pikRes = securityOpt.saveKey(AidlConstants.Security.KEY_TYPE_PIK, key, checkValue, TMKIndex, KEY_ALG_TYPE_3DES, PIKIndex, true);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (pikRes != 0) {
            LogUtil.e(Constant.TAG, "PIK CHECKVALUE ERROR");
            return pikRes;
        }

        // Save MAK
        if (FieldConfig.MAC_CHECK_IS_3DES) {
            System.arraycopy(workingKeyBytes, index * (keyLength + 4), key, 0, keyLength);
        } else {
            key = new byte[8];
            System.arraycopy(workingKeyBytes, index * (keyLength + 4), key, 0, keyLength - 8);
        }
        System.arraycopy(workingKeyBytes, index * (keyLength + 4) + keyLength, checkValue, 0, 4);
        LogUtil.e(Constant.TAG, "MAK CheckValue：" + Utils.byte2HexStr(checkValue));
        LogUtil.e(Constant.TAG, "saveMAK："
                + "\n 保存到索引：" + MAKIndex
                + "\n 密钥类型：5 \n 解密密钥索引：" + TMKIndex
                + "\n 加密类型：3 \n mak密文：" + Arrays.toString(key)
                + "\n length：" + key.length);
        int makRes = -1;
        try {
            makRes = securityOpt.saveKey(AidlConstants.Security.KEY_TYPE_MAK, key, checkValue, TMKIndex, KEY_ALG_TYPE_3DES, MAKIndex, true);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (makRes != 0) {
            LogUtil.e(Constant.TAG, "MAK CHECKVALUE ERROR");
            return makRes;
        } else if (makRes == 0 && FieldConfig.MAC_CHECK_IS_3DES && !FieldConfig.MAC_IS_3DES) {
            makRes = -1;
            key = new byte[8];
            System.arraycopy(workingKeyBytes, index * (keyLength + 4), key, 0, keyLength - 8);
            try {
                makRes = securityOpt.saveKey(AidlConstants.Security.KEY_TYPE_MAK, key, null, TMKIndex, KEY_ALG_TYPE_3DES, MAKIndex, true);
                LogUtil.e(Constant.TAG, "save MAK : " + makRes);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            if (makRes != 0) {
                LogUtil.e(Constant.TAG, "MAK SAVE ERROR");
                return makRes;
            }
        }
        index++;
        // Save TDK
        if (trackEncode) {
            key = new byte[keyLength];
            System.arraycopy(workingKeyBytes, index * (keyLength + 4), key, 0, keyLength);
            System.arraycopy(workingKeyBytes, index * (keyLength + 4) + keyLength, checkValue, 0, 4);
            LogUtil.e(Constant.TAG, "TDK CheckValue：" + Utils.byte2HexStr(checkValue));
            LogUtil.e(Constant.TAG, "saveTDK："
                    + "\n 保存到索引：" + TDKIndex
                    + "\n 密钥类型：5 \n 解密密钥索引：" + TMKIndex
                    + "\n 加密类型：3 \n tdk密文：" + Arrays.toString(key)
                    + "\n length：" + key.length);
            int tdkRes = -1;
            try {
                tdkRes = securityOpt.saveKey(AidlConstants.Security.KEY_TYPE_TDK, key, checkValue, TMKIndex, KEY_ALG_TYPE_3DES, TDKIndex, true);
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (tdkRes != 0) {
                LogUtil.e(Constant.TAG, "TDK CHECKVALUE ERROR");
                return tdkRes;
            }
        }
        return 0;
    }

    public static void GenerateMAC(byte[] data) {
        SecurityOptV2 securityOptV2 = MyApplication.getInstance().mSecurityOptV2;

        // copy
        byte[] dataIn = new byte[data.length - 21];
        System.arraycopy(data, 13, dataIn, 0, data.length - 21);


        byte[] dataOut = new byte[8];
        try {
            int result = securityOptV2.calcMac(Constant.indexMAK, AidlConstantsV2.Security.MAC_ALG_X9_19, dataIn, dataOut);
            LogUtil.e(Constant.TAG, "硬加密 result：" + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        String hexStr = ByteUtil.bytes2HexStr(dataOut);
        LogUtil.e(Constant.TAG, "硬加密：" + hexStr);
        System.arraycopy(dataOut, 0, data, data.length - 8, 8);
    }

    public static void initKeyIndex() {
        TerminalKeyManagementBean terminalKeyManagementBean = TerminalKeyDataOperations.getInstance().getTerminalKeyManagementBean();
        if (terminalKeyManagementBean == null || TextUtils.isEmpty(terminalKeyManagementBean.getDes())) {
            encryptionAlgorithm = THREE_DES;
        } else {
            encryptionAlgorithm = terminalKeyManagementBean.getDes();
        }
        int index;
        try {
            index = Integer.parseInt(terminalKeyManagementBean.getTerminalKeyIndex());
        } catch (Exception e) {
            index = 0;
        }
        PIKIndex = SecurityKeyAreaDistribution.getPIKIndex(encryptionAlgorithm, index);
        MAKIndex = SecurityKeyAreaDistribution.getMAKIndex(encryptionAlgorithm, index);
        TDKIndex = SecurityKeyAreaDistribution.getTDKIndex(encryptionAlgorithm, index);
        TMKIndex = SecurityKeyAreaDistribution.getTMKIndex(encryptionAlgorithm, index);
        KEKIndex = SecurityKeyAreaDistribution.getKEKIndex(index);
    }

    /**
     * 保存密钥到芯片
     *
     * @param index1      需要保存的密钥索引，1~99
     * @param index2      需要保存的密钥类型索引，1为主密钥；2为PIN密钥；3为MAC密钥；4为PAN密钥；5为自定义密钥
     * @param index3      指定解密密文的密钥索引，1~99；
     * @param encryptType 密钥密文的加密方式，1表示没加密；2表示DES；3表示TDES；4表示RSA公钥
     * @param key         密钥数据
     * @param keyLength   密钥数据长度
     * @return 等于0：密钥保存成功；等于4：密钥重复；其他：密钥保存错误。
     */
    public static synchronized int saveKey(int index1, int index2, int index3, int encryptType, byte[] key, int keyLength) {
        SecurityOpt securityOpt = MyApplication.getInstance().securityOpt;
        int result = -1;
        try {
            if (index1 == TMKIndex) {
                result = securityOpt.saveKey(AidlConstants.Security.KEY_TYPE_TMK, key, null, index3, KEY_ALG_TYPE_3DES, index1, true);
            } else if (index1 == PIKIndex) {
                result = securityOpt.saveKey(AidlConstants.Security.KEY_TYPE_TMK, key, null, index3, KEY_ALG_TYPE_3DES, index1, true);
            } else {
                result = securityOpt.saveKey(AidlConstants.Security.KEY_TYPE_REC, key, null, index3, KEY_ALG_TYPE_3DES, index1, true);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        LogUtil.e(Constant.TAG, "saveKey result：" + result);
        return result;
    }

    /**
     * 使用安全芯片中密钥加密数据
     *
     * @param keyIndex    加密密钥索引，1~99
     * @param keyType     加密密钥类型索引，2为PIN密钥；3为MAC密钥；4为PAN密钥；5为自定义密钥
     * @param encryptType 加密方式，2表示DES；3表示TDES；4表示RSA公钥
     * @param plaintext   待加密的明文数据
     * @param outArr      加密完的密文数据
     * @return 大于0：加密成功；其他：加密错误
     */
    public static synchronized int dataEncrypt(int keyIndex, int keyType, int encryptType, byte[] plaintext, byte[] outArr) {
        SecurityOpt securityOpt = MyApplication.getInstance().securityOpt;
        LogUtil.e(Constant.TAG, "dataEncrypt 密钥索引：" + keyIndex
                + "\n 密钥类型：" + keyType
                + "\n 加密类型：" + encryptType
                + "\n 数据：" + Arrays.toString(plaintext)
                + "\n hex:" + Utils.byte2HexStr(plaintext));
        int result = -1;
        try {
            result = securityOpt.dataEncrypt(keyIndex, plaintext, outArr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        String bytesToHexString = Utils.byte2HexStr(outArr);
        LogUtil.e(Constant.TAG, "dataEncrypt result：" + result + " 加密结果：" + bytesToHexString);
        return result;
    }

    public static synchronized int saveKEK(String kekStr) {
        SecurityOpt securityOpt = MyApplication.getInstance().securityOpt;
        int index = KEKIndex;
        byte[] kek = Utils.hexStr2Bytes(kekStr);
        KeyEncryptKey = kek;
        LogUtil.e(Constant.TAG, "saveKEK："
                + "\n 保存到索引：" + index
                + "\n 密钥类型：1 \n 解密密钥索引：0"
                + "\n 加密类型：1 \n key_data：" + Arrays.toString(kek)
                + "\n length：" + kek.length);
        int result = -1;
        try {
            result = securityOpt.saveKey(AidlConstants.Security.KEY_TYPE_KEK, kek, null, 1, KEY_ALG_TYPE_3DES, KEKIndex, false);
        } catch (Exception e) {
            e.printStackTrace();
        }
        LogUtil.e(Constant.TAG, "saveKEK：" + result);
        return result;
    }

    public static synchronized int saveKEK(byte[] kek) {
        SecurityOpt securityOpt = MyApplication.getInstance().securityOpt;
        KeyEncryptKey = kek;
        TerminalKeyDataOperations.getInstance().saveKEK(Utils.byte2HexStr(kek));
        int index = KEKIndex;
        LogUtil.e(Constant.TAG, "saveKEK："
                + "\n 保存到索引：" + index
                + "\n 密钥类型：1 \n 解密密钥索引：0"
                + "\n 加密类型：1 \n key_data：" + Utils.byte2HexStr(kek)
                + "\n length：" + kek.length);
        int result = -1;

        try {
            result = securityOpt.saveKey(AidlConstants.Security.KEY_TYPE_KEK, kek, null, 1, KEY_ALG_TYPE_3DES, KEKIndex, false);
        } catch (Exception e) {
            e.printStackTrace();
        }
        LogUtil.e(Constant.TAG, "saveKEK：" + result);
        return result;
    }

    public static byte[] XOR(byte[] a1, byte[] a2) {
        if ((a1 == null) || (a2 == null)) {
            return null;
        }
        if (a1.length == 0) {
            return null;
        }
        if (a1.length != a2.length) {
            return null;
        }
        byte[] a = new byte[a1.length];
        for (int i = 0; i < a.length; i++) {
            a[i] = (byte) (a1[i] ^ a2[i]);
        }
        return a;
    }

}
